//FACEBOOK ASYNC CLIENT

//FacebookAsyncUser methods

#include "facebookasync.h"

#include "xmlParser.h"
#include "md5.h"
#include <fstream>
#include <iostream>

//FETCHING INFO RELATED ROUTINES

bool FacebookAsyncUser::StartFetchingInfo()
{
	assert(m_CurLoginStage == LOGINSTAGE_SUCCEED);
	assert(m_CurInfoStage == INFOSTAGE_NOTSTARTED || m_CurInfoStage == INFOSTAGE_FAILED);

	m_CurInfoStage = INFOSTAGE_NOTSTARTED;

	m_FriendsIDs.clear();
	m_FriendsProfileInfo.clear(); 
	m_FriendsPhotos.clear(); 

	//starting first info stage
	InfoStartStage_GettingUserInfo(); 

	return true;
}//bool FacebookAsyncUser::StartLogin()


void FacebookAsyncUser::InfoStartStage_GettingUserInfo()
{
	assert(m_HasActiveRequest == false);


	std::list<std::string> Params;
	std::string XmlResult;
	
	Params.push_back("uids=" + m_UserID);
	Params.push_back("fields=" + std::string(FACEBOOK_PROFILEINFOQUERY)); 

	FacebookAsync::Instance().Helper_PrepareAPICall("facebook.users.getInfo", Params, this); 

	PushNewRequest();

	m_CurInfoStage = INFOSTAGE_GETTINGUSERINFO; 

	FacebookAsync::Instance().MakeCallback();
}


void FacebookAsyncUser::InfoOnStageDone_GettingUserInfo()
{
	assert(m_CurInfoStage == INFOSTAGE_GETTINGUSERINFO);

	PullCompletedRequest();

	if (m_CurRequestResult.size() < 1)
	{
		FacebookAsync::Instance().SetErrorDescription("InfoOnStageDone_GettingUserInfo(). Request failed!");
		m_CurInfoStage = INFOSTAGE_FAILED;
		FacebookAsync::Instance().MakeCallback();
		return;
	}

	XMLNode Head = XMLNode::parseString(m_CurRequestResult.c_str( ), NULL);
	XMLNode Result = Head.getChildNode(_T("users_getInfo_response"));

	//user node
	XMLNode UserNode = Result.getChildNode(_T("user"));

	//parsing profile info
	FacebookAsync::Instance().Helper_ParseProfileInfo(UserNode, m_UserProfileInfo);

    //checking if name is not empty
	if (m_UserProfileInfo.Name.size() > 0)
	{
		//success - to the next stage!
		InfoStartStage_GettingUserPhotoSize(); 
		
	}
	else
	{
		//failure
		FacebookAsync::Instance().SetErrorDescription("InfoOnStageDone_GettingUserInfo(). Request returned no data!");
		m_CurInfoStage = INFOSTAGE_FAILED;
		FacebookAsync::Instance().MakeCallback();
		return;	
	}
}



void FacebookAsyncUser::InfoStartStage_GettingUserPhotoSize()
{
	assert(m_HasActiveRequest == false);

	if (m_UserProfileInfo.PhotoURL.size() < 3)
	{
		//starting next info stage
		m_UserProfileInfo.PhotoSize.Width = 0;
		m_UserProfileInfo.PhotoSize.Height= 0;
		InfoStartStage_GettingFriends();
		return;
	}

	FacebookAsync::Instance().Helper_PrepareGetPhotoSizeCall(this, m_UserProfileInfo.PhotoURL);  

	PushNewRequest();

	m_CurInfoStage = INFOSTAGE_GETTINGUSERPHOTOSIZE; 

	FacebookAsync::Instance().MakeCallback();
}


void FacebookAsyncUser::InfoOnStageDone_GettingUserPhotoSize()
{
	assert(m_CurInfoStage == INFOSTAGE_GETTINGUSERPHOTOSIZE);

	PullCompletedRequest();

	FacebookAsync::Instance().Helper_ParsePhotoSize(m_CurRequestResult, m_UserProfileInfo.PhotoSize); 

	InfoStartStage_GettingFriends();
}


void FacebookAsyncUser::InfoStartStage_GettingFriends()
{
	assert(m_HasActiveRequest == false);

	std::list<std::string> Params;

	FacebookAsync::Instance().Helper_PrepareAPICall("facebook.friends.get", Params, this); 

	PushNewRequest();

	m_CurInfoStage = INFOSTAGE_GETTINGFRIENDS;

	FacebookAsync::Instance().MakeCallback();
}


void FacebookAsyncUser::InfoOnStageDone_GettingFriends()
{

	assert(m_CurInfoStage == INFOSTAGE_GETTINGFRIENDS);

	PullCompletedRequest();

	XMLNode Head = XMLNode::parseString(m_CurRequestResult.c_str( ), NULL);
	XMLNode Result = Head.getChildNode(_T("friends_get_response"));

	int FriendsCount = Result.nChildNode(_T("uid"));

	if (FriendsCount == 0)
	{
		//no need to continue - no friends
		FacebookAsync::Instance().SetErrorDescription("");
		m_CurInfoStage = INFOSTAGE_SUCCEED;
		FacebookAsync::Instance().MakeCallback();
		return;
	}

	//resizing vectors
	m_FriendsIDs.resize(FriendsCount);
	m_FriendsProfileInfo.resize(FriendsCount); 
	m_FriendsPhotos.resize(FriendsCount, ""); 

	//remembering friends ids
	XMLNode CurNode;

	int i;

	for (i = 0; i < FriendsCount; i++)
	{
		CurNode = Result.getChildNode(_T("uid"), FriendsCount - 1 - i);
		assert(!(CurNode.isEmpty()));
		m_FriendsIDs.at(FriendsCount - 1 - i) = CurNode.getText();
	}

	InfoStartStage_GettingFriendsInfo();

}


void FacebookAsyncUser::InfoStartStage_GettingFriendsInfo()
{
	assert(m_HasActiveRequest == false);

	std::list<std::string> Params;
	Params.clear();

	std::string FriendsIDsString = "uids=";
	int i;
	for (i = 0; i < (int)m_FriendsIDs.size(); i++)
	{
		FriendsIDsString.append(m_FriendsIDs.at(i));
		if (i != m_FriendsIDs.size() - 1)
			FriendsIDsString.append(",");
	}

	Params.push_back(FriendsIDsString);
	Params.push_back("fields=" + std::string(FACEBOOK_PROFILEINFOQUERY)); 

	FacebookAsync::Instance().Helper_PrepareAPICall("facebook.users.getInfo", Params, this); 


	PushNewRequest();

	m_CurInfoStage = INFOSTAGE_GETTINGFRIENDSINFO;

	FacebookAsync::Instance().MakeCallback();

}


void FacebookAsyncUser::InfoOnStageDone_GettingFriendsInfo()
{

	assert(m_CurInfoStage == INFOSTAGE_GETTINGFRIENDSINFO);

	PullCompletedRequest();


	XMLNode Head = XMLNode::parseString(m_CurRequestResult.c_str( ), NULL);
	XMLNode Result = Head.getChildNode(_T("users_getInfo_response"));

	int FriendsInfoCount = Result.nChildNode(_T("user"));

	if (m_FriendsIDs.size()  != FriendsInfoCount)
	{
		//failure
		FacebookAsync::Instance().SetErrorDescription("facebook.users.getInfo request returned invalid number of entries!");
		m_CurInfoStage = INFOSTAGE_FAILED;
		FacebookAsync::Instance().MakeCallback();
		return;	
	}

	XMLNode ChildNode;
	XMLNode CurNode;
	int i;

	for (i = 0; i < FriendsInfoCount; i++)
	{
		CurNode = Result.getChildNode(_T("user"), FriendsInfoCount - 1 - i);
		assert(!(CurNode.isEmpty()));
		ChildNode = CurNode.getChildNode(_T("uid"));
		assert(!(ChildNode.isEmpty()));
		std::string CurUserID = ChildNode.getText();

		assert(CurUserID == m_FriendsIDs.at(FriendsInfoCount - 1 - i));

		FacebookAsync::Instance().Helper_ParseProfileInfo(CurNode, m_FriendsProfileInfo.at(FriendsInfoCount - 1 - i)); 
	}

	//building app and non-app friends indexes vectors
	FacebookAsync::Instance().Helper_BuildAppAndNonAppVectors(this);

	InfoStartStage_GettingFriendsPhotoSizes(); 

}


void FacebookAsyncUser::InfoStartStage_GettingFriendsPhotoSizes() 
{
	assert(m_HasActiveRequest == false);

	m_CurFriendToProcess = 0;

	InfoContinueStage_GettingFriendsPhotoSizes();
}



void FacebookAsyncUser::InfoContinueStage_GettingFriendsPhotoSizes()
{
	assert(m_HasActiveRequest == false);

	while(m_CurFriendToProcess < (int)m_FriendsProfileInfo.size())
	{

		if (m_FriendsProfileInfo.at(m_CurFriendToProcess).PhotoURL.size() > 3)
			break;
		else
		{
			m_FriendsProfileInfo.at(m_CurFriendToProcess).PhotoSize.Width = 0;
			m_FriendsProfileInfo.at(m_CurFriendToProcess).PhotoSize.Height = 0;
			m_CurFriendToProcess++;
		}
	}

	if (m_CurFriendToProcess >= (int)m_FriendsProfileInfo.size())
	{
		//no photo sizes to fetch
		FacebookAsync::Instance().SetErrorDescription("");
		m_CurInfoStage = INFOSTAGE_SUCCEED;
		FacebookAsync::Instance().MakeCallback();

		if (m_AutoFetch == true)
			FacebookAsync::Instance().CurUser_StartFetchingPhotos(); 

		return;
	}

	FacebookAsync::Instance().Helper_PrepareGetPhotoSizeCall(this, m_FriendsProfileInfo.at(m_CurFriendToProcess).PhotoURL);    

	PushNewRequest();

	m_CurInfoStage = INFOSTAGE_GETTINGFRIENDSPHOTOSIZES; 

	FacebookAsync::Instance().MakeCallback();
}



void FacebookAsyncUser::InfoOnStageDone_GettingFriendsPhotoSizes()
{

	assert(m_CurInfoStage == INFOSTAGE_GETTINGFRIENDSPHOTOSIZES);

	PullCompletedRequest();

	FacebookAsync::Instance().Helper_ParsePhotoSize(m_CurRequestResult, m_FriendsProfileInfo.at(m_CurFriendToProcess).PhotoSize); 

	m_CurFriendToProcess++;

	InfoContinueStage_GettingFriendsPhotoSizes();

}

